package com.zrulin.ftcommunity;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.RedisStringCommands;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;

/**
 * @author zrulin
 * @create 2022-07-12 9:23
 */
@SpringBootTest
public class RedisTest1 {

    @Autowired
    private RedisTemplate redisTemplate;

    @Test
    public void hyperLogLogTest(){
        String redisKey = "test:hll:01";

        for (int i = 0; i < 1000; i++) {
            redisTemplate.opsForHyperLogLog().add(redisKey, i);
        }
        for (int i = 0; i < 1000; i++) {
            int r = (int) (Math.random() * 1000 + 1);
            redisTemplate.opsForHyperLogLog().add(redisKey, r);
        }
        Long size = redisTemplate.opsForHyperLogLog().size(redisKey);
        System.out.println(size);
    }

    @Test
    public void tetBitMap(){
        String redisKey = "test:bm:01";

        //记录,索引从零开始
        redisTemplate.opsForValue().setBit(redisKey, 1, true);
        redisTemplate.opsForValue().setBit(redisKey, 4, true);
        redisTemplate.opsForValue().setBit(redisKey, 7, true);
    }
    @Test
    public void tetBitMapSelect(){
        String redisKey = "test:bm:01";

        //查询
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 1));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 3));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 2));

        //统计。通过redis底层的连接才能够访问统计的方法
        //怎么获取底层的连接：它在调用execute方法的时候，实现RedisCallback回调接口的doInRedis会自动的传入connection底层的连接，
        // 可以利用这个方法返回一些东西。
        Object obj = redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                //返回字节数组里面1的个数
                return connection.bitCount(redisKey.getBytes());
            }
        });
        System.out.println(obj);
    }

    //统计3组数据的布尔值，并对这三组数据做OR运算
    @Test
    public void tetBitMapSelect1(){
        String redisKey2 = "test:bm:02";

        //查询
        redisTemplate.opsForValue().setBit(redisKey2,1,true);
        redisTemplate.opsForValue().setBit(redisKey2, 2,true);
        redisTemplate.opsForValue().setBit(redisKey2, 3, true);

        String redisKey3 = "test:bm:03";

        //查询
        redisTemplate.opsForValue().setBit(redisKey3,2,true);
        redisTemplate.opsForValue().setBit(redisKey3, 3,true);
        redisTemplate.opsForValue().setBit(redisKey3, 4, true);
        String redisKey4 = "test:bm:04";

        //查询
        redisTemplate.opsForValue().setBit(redisKey4,4,true);
        redisTemplate.opsForValue().setBit(redisKey4, 5,true);
        redisTemplate.opsForValue().setBit(redisKey4, 6, true);

        //统计。通过redis底层的连接才能够访问统计的方法
        //怎么获取底层的连接：它在调用execute方法的时候，实现RedisCallback回调接口的doInRedis会自动的传入connection底层的连接，
        // 可以利用这个方法返回一些东西。
        String redisKey = "test:bm:00";
        Object obj = redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection connection) throws DataAccessException {
                //返回字节数组里面1的个数
                connection.bitOp(RedisStringCommands.BitOperation.OR,
                        redisKey.getBytes(),
                        redisKey2.getBytes(),
                        redisKey3.getBytes(),
                        redisKey4.getBytes());
                return connection.bitCount(redisKey.getBytes());
            }
        });
        System.out.println(obj);

        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 0));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 1));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 2));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 3));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 4));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 5));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 6));
        System.out.println(redisTemplate.opsForValue().getBit(redisKey, 7));
    }
}
